﻿using System;
using System.ServiceModel;
using System.Runtime.Serialization;

namespace MultiViewer.Network
{
    [DataContract]
    public class Message
    {
        public const int UnknownSender = -1;

        private int sender;

        public Message()
        {
            sender = UnknownSender;
        }

        public Message(int sender)
        {
            this.sender = sender;
        }
        
        [DataMember]
        public int Sender
        {
            get { return sender; }
            set { sender = value; }
        }
    }

    [ServiceContract(Namespace="http://microsoft.cs.msu.su/multiviewer/2.0/server",
        CallbackContract=typeof(IClientNode))]
    public interface IServerNode
    {
        /// <summary>Asks server to connect client</summary>
        /// <param name="nodeId">Id of node</param>
        /// <returns>Total number of nodes in network</returns>
        [OperationContract]
        int Connect(int nodeId);

        /// <summary>Asks server to disconnect client</summary>
        /// <param name="nodeId">Id of node</param>
        [OperationContract(IsOneWay=true)]
        void Disconnect(int nodeId);

        [OperationContract(IsOneWay = true)]
        void Notify(int[] nodes, Message message);

        [OperationContract]
        Response[] Send(int[] nodes, Message message);

        [OperationContract(IsOneWay=true)]
        void Perform(Message message);
    }

    [ServiceContract(Namespace="http://microsoft.cs.msu.su/multiviewer/2.0/client")]
    public interface IClientNode
    {
        /// <summary>This method is invoked by server to inform client about server shutdown</summary>
        [OperationContract(IsOneWay = true)]
        void Shutdown();

        /// <summary>This method is invoked by server to inform client about notification message</summary>
        /// <param name="sender">Node that broadcast this notification</param>
        /// <param name="message">Message</param>
        [OperationContract(IsOneWay = true)]
        void OnNotification(Message message);

        [OperationContract]
        object OnMessage(Message message);

        /// <summary>This method is invoked by server to start first phase of 
        /// transaction - prepare</summary>
        /// <param name="id">Transaction id</param>
        /// <param name="message">Message for preparation</param>
        /// <returns>True if succeeded or false otherwise</returns>
        [OperationContract]
        bool OnPrepare(string id, Message message);

        [OperationContract(IsOneWay=true)]
        void OnCommit(string id);

        [OperationContract(IsOneWay = false)]
        void OnRollback(string id);
    }
}